import axios from "axios";
import { Local,Session } from "@/utils";
import { TOKEN_KEY,REFRESH_ACCESS_TOKEN_KEY } from "@/const";
import { getToken ,getRefreshToken} from "@/utils/signalR";
import { clearToken } from "@/utils";
import { showMsg } from "@/utils";
import {stopSignalR} from '@/utils/signalR'

export const request = axios.create({
    baseURL: '',
    timeout: 300000,
});

request.interceptors.request.use(function (config) {
    const accessToken = getToken()
    if(accessToken){
        // 携带token
        config.headers['Authorization'] = `Bearer ${accessToken}`
        const jwt = decryptJWT(accessToken) //获取jwt数据部分
        const exp = getJWTDate(jwt.exp)
        if(new Date() > exp) {
            // token过期
            const refreshAccessToken = getRefreshToken()
            			// 携带刷新 token
		    if (refreshAccessToken) {
		    	config.headers!['X-Authorization'] = `Bearer ${refreshAccessToken}`;
		    }
        }
        if(config.method?.toLowerCase() == 'get' && config.data){
            // get参数映射,get请求的参数若在请求体中则映射到url地址后
            let url = config.url + '?' + tansParams(config.data)
            url = url.slice(0,-1) //去除最后一个&
            config.url = url
            config.data = {}
        }
    }
    return config;
}, function (error) {
    return Promise.reject(error);
});

request.interceptors.response.use(function (response) {
    var status = response.status //axios返回的状态码
    var serve = response.data // 服务端返回的数据,包含自定义的状态码

    // 未授权或授权失败
    if(status === 401) {
        clearAccessAfterReload()
    }
    // 处理未进行规范化处理的
    if(status >= 400){
        throw new Error(response.statusText || 'Request Error.');
    }
    
    // 处理规范化结果错误
    if (serve && serve.hasOwnProperty('errors') && serve.errors) {
        throw new Error(JSON.stringify(serve.errors || 'Request Error.'));
    }
    		// 读取响应报文头 token 信息
	var accessToken = response.headers[TOKEN_KEY]
	var refreshAccessToken = response.headers[REFRESH_ACCESS_TOKEN_KEY];
	// 判断是否是无效 token
	if (accessToken === 'invalid_token') {
		clearAccessAfterReload();
	}else if(accessToken && refreshAccessToken){
        // 若返回的结果存在刷新token则必定存在token，存储本地
        Local.set(TOKEN_KEY,accessToken)
        Local.set(REFRESH_ACCESS_TOKEN_KEY,refreshAccessToken)
        Session.set(TOKEN_KEY,accessToken)
        Session.set(REFRESH_ACCESS_TOKEN_KEY,refreshAccessToken)
    }

    // 若自定义code为401则视为未授权
    if(serve.code == 401){
        clearAccessAfterReload()
    }else if(serve.code === undefined){
        return Promise.resolve(response)
    }else if (serve.code !== 200){
        let msg = ''
        if(serve.message && typeof serve.message === 'object'){
            msg = JSON.stringify(serve.message)
        }else {
            msg = serve.message
        }
        
        showMsg(msg,'error')
        throw new Error(msg)
    }
    return response;
}, function (error) {
    return Promise.reject(error);
});

export function decryptJWT(token:string){
    // 不是真的解密只是获取加密的数据
    // 替换特殊字符
    token = token.replace(/_/g,'/').replace(/-/g,'+')
    /* 
        token 由三部分组成
        1. header 头部
        2. payload 负载
        3. signature 签名
    */
    // 取出token中的具体加密内容
    const payload = token.split('.')[1]
    // escape,decodeURIComponent处理Unicode字符加密解码
    var json = decodeURIComponent(escape(window.atob(payload)))
    //#region 
    // json内容
    // {
    //     "UserId": 1300000000101,
    //     "TenantId": 1300000000001,
    //     "Account": "superadmin",
    //     "RealName": "超级管理员",
    //     "AccountType": 999,
    //     "OrgId": 0,
    //     "OrgName": null,
    //     "OrgType": null,
    //     "iat": 1742874002,
    //     "nbf": 1742874002,
    //     "exp": 1743478802,
    //     "iss": "Admin.NET",
    //     "aud": "Admin.NET"
    // }
    //#endregion
    return JSON.parse(json)
}

/**
 * 将 JWT 时间戳转换成 Date
 * @description 主要针对 `exp`，`iat`，`nbf`
 * @param timestamp 时间戳
 * @returns Date 对象
 */
export function getJWTDate(timestamp:number):Date{
    return new Date(timestamp * 1000)
}

export function tansParams(params:any){
    // params默认是对象结构
    let result = ''
    for(const propName of Object.keys(params)){
        let value = params[propName]
        var part = encodeURIComponent(propName) + "=" // ?name = zq & age = 18
        if(value != null && value != '' && typeof value != 'undefined'){
            if(typeof value =='object'){
                // 若value是对象
                for(const key of Object.keys(value)){
                    if(value[key] != null && value[key] != '' && typeof value[key] !='undefined'){
                        let params = propName + '[' + key + ']' //url: '/api/users?name=zhang&age=18&address[city]=beijing&address
                        let subPart = encodeURIComponent(params) + "="
                        result += subPart + encodeURIComponent(value[key]) + '&'
                    }
                }
            }else {
                result += part + encodeURIComponent(value) + '&'
            }
        }
    }
    return result
}


export async function clearAccessAfterReload(){
    clearToken()
    await stopSignalR() // 断开连接
    // 清除token后会字段进入路由重定向到首页
    window.location.reload()
}